<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="xli6T" id="xli6T"><span data-lake-id="u55e3b328" id="u55e3b328">典型回答</span></h1>
  <p data-lake-id="u1f3f40e3" id="u1f3f40e3"><span data-lake-id="u2ead25d0" id="u2ead25d0">多态的概念比较简单，</span><strong><span data-lake-id="u8227c148" id="u8227c148">就是同一操作作用于不同的对象，可以有不同的解释，产生不同的执行结果。</span></strong></p>
  <p data-lake-id="u8ef63b37" id="u8ef63b37"><span data-lake-id="u18abe9c4" id="u18abe9c4">​</span><br></p>
  <p data-lake-id="u9139d968" id="u9139d968"><span data-lake-id="u64c87b40" id="u64c87b40">如果按照这个概念来定义的话，那么多态应该是一种运行期的状态。为了实现运行期的多态，或者说是动态绑定，需要满足三个条件：</span></p>
  <p data-lake-id="u5598b464" id="u5598b464"><span data-lake-id="ub6a1000f" id="ub6a1000f">​</span><br></p>
  <ul list="u80fb2f85">
   <li fid="u383032e3" data-lake-id="ua3532536" id="ua3532536"><span data-lake-id="uffd19245" id="uffd19245">有类继承或者接口实现。</span></li>
   <li fid="u383032e3" data-lake-id="u20cdc93d" id="u20cdc93d"><span data-lake-id="u48c9c6b5" id="u48c9c6b5">子类要重写父类的方法。</span></li>
   <li fid="u383032e3" data-lake-id="u4e578c85" id="u4e578c85"><span data-lake-id="u8723ba53" id="u8723ba53">父类的引用指向子类的对象。</span></li>
  </ul>
  <p data-lake-id="ud56df213" id="ud56df213"><br></p>
  <p data-lake-id="uad40d44d" id="uad40d44d"><span data-lake-id="ud0c38411" id="ud0c38411">简单来一段代码解释下：</span></p>
  <p data-lake-id="ufedf439c" id="ufedf439c"><br></p>
  <pre lang="java"><code>
public class Parent{

    public void call(){
        sout("im Parent");
    }
}
public class Son extends Parent{// 1.有类继承或者接口实现
    public void call(){// 2.子类要重写父类的方法
        sout("im Son");
    }
}
public class Daughter extends Parent{// 1.有类继承或者接口实现
    public void call(){// 2.子类要重写父类的方法
        sout("im Daughter");
    }
}
public class Test{

    public static void main(String[] args){
        Parent p = new Son(); //3.父类的引用指向子类的对象
        Parent p1 = new Daughter(); //3.父类的引用指向子类的对象
    }
}
</code></pre>
  <p data-lake-id="u32086d96" id="u32086d96"><br></p>
  <p data-lake-id="ub92c3515" id="ub92c3515"><span data-lake-id="ue5413018" id="ue5413018">这样，就实现了多态，同样是Parent类的实例，p.call 调用的是Son类的实现、p1.call调用的是Daughter的实现。</span></p>
  <p data-lake-id="ue47ae20b" id="ue47ae20b"><span data-lake-id="uf0c05b4a" id="uf0c05b4a">​</span><br></p>
  <p data-lake-id="uf73d778c" id="uf73d778c"><span data-lake-id="u853a383a" id="u853a383a">有人说，你自己定义的时候不就已经知道p是son，p1是Daughter了么。</span><u><span data-lake-id="u5a2ed23f" id="u5a2ed23f">但是，有些时候你用到的对象并不都是自己声明的 。</span></u></p>
  <p data-lake-id="u2b5a1813" id="u2b5a1813"><span data-lake-id="u93e2c3b0" id="u93e2c3b0">​</span><br></p>
  <p data-lake-id="uf17325db" id="uf17325db"><span data-lake-id="u9e7b4017" id="u9e7b4017">比如Spring 中的IOC出来的对象，你在使用的时候就不知道他是谁，或者说你可以不用关心他是谁。根据具体情况而定。</span></p>
  <p data-lake-id="ubc8d42b6" id="ubc8d42b6"><span data-lake-id="u0e6f50cf" id="u0e6f50cf">​</span><br></p>
  <p data-lake-id="ud9240a14" id="ud9240a14"><span data-lake-id="u08627a54" id="u08627a54">如下面的payService就不是我们自己创建的，而是在运行期根据channel实时决策出来的。</span></p>
  <pre lang="java"><code>
public class PayDomainService {
    @Autowired
    PayServiceFactory payServiceFactory;

    public void pay(PayRequest payRequest) {
        String payChannel = payRequest.getPayChannel();
        payServiceFactory.getPayService(payChannel).pay(payRequest);
    }
}
</code></pre>
  <p data-lake-id="ucebd1e0b" id="ucebd1e0b"><span data-lake-id="u61a55bc6" id="u61a55bc6">​</span><br></p>
  <p data-lake-id="ud78f133b" id="ud78f133b"><span data-lake-id="uee36d839" id="uee36d839">前面说多态是一种运行期的概念。还有一种说法，包括维基百科也说明，认为多态还分为动态多态和静态多态。</span></p>
  <p data-lake-id="u724352fe" id="u724352fe"><span data-lake-id="u58232cd9" id="u58232cd9">​</span><br></p>
  <p data-lake-id="ua37de3b9" id="ua37de3b9"><span data-lake-id="u2e46f29d" id="u2e46f29d">一般认为Java中的函数重载是一种静态多态，因为他需要在编译期决定具体调用哪个方法。关于这一点，不同的人有不同的见解，建议在面试中如果被问到，可以这样回答：</span></p>
  <p data-lake-id="u56eaf378" id="u56eaf378"><span data-lake-id="u80970b73" id="u80970b73">​</span><br></p>
  <blockquote data-lake-id="u41bfe49a" id="u41bfe49a">
   <p data-lake-id="u75cb8287" id="u75cb8287"><span data-lake-id="u4dc91534" id="u4dc91534">“我认为，多态应该是一种运行期特性，Java中的重写是多态的体现。不过也有人提出重载是一种静态多态的想法，这个问题在StackOverflow等网站上有很多人讨论，但是并没有什么定论。我更加倾向于重载不是多态。”</span></p>
  </blockquote>
  <p data-lake-id="u219ad508" id="u219ad508"><span data-lake-id="ubda99bb1" id="ubda99bb1">​</span><br></p>
  <p data-lake-id="u405087f8" id="u405087f8"><span data-lake-id="u150dcf09" id="u150dcf09">这样沟通，既能体现出你了解的多，又能表现出你有自己的思维，不是那种别人说什么就是什么的。</span></p>
  <p data-lake-id="ud6e68b15" id="ud6e68b15"><br></p>
  <h1 data-lake-id="ocQ1F" id="ocQ1F"><span data-lake-id="u0b456385" id="u0b456385">扩展知识</span></h1>
  <h3 data-lake-id="Gxly5" id="Gxly5"><span data-lake-id="uf0b9f900" id="uf0b9f900">方法的重载与重写</span></h3>
  <p data-lake-id="u95e21f6d" id="u95e21f6d"><br></p>
  <p data-lake-id="u2ccdf1ac" id="u2ccdf1ac"><span data-lake-id="u5713e0e9" id="u5713e0e9">重载是就是函数或者方法有同样的名称，但是参数列表不相同的情形，这样的同名不同参数的函数或者方法之间，互相称之为重载函数或者方法。</span></p>
  <p data-lake-id="u03463799" id="u03463799"><span data-lake-id="u0dadf863" id="u0dadf863">​</span><br></p>
  <pre lang="java"><code>
class HollisExample {
    // 方法重载 - 第一个方法
    public void display(int a) {
        System.out.println("Got Integer data.");
    }

    // 方法重载 - 第二个方法
    public void display(String b) {
        System.out.println("Got String data.");
    }
}

</code></pre>
  <p data-lake-id="u88bd6657" id="u88bd6657"><br></p>
  <p data-lake-id="u57dcf87c" id="u57dcf87c"><span data-lake-id="ue2888e3a" id="ue2888e3a">重写指的是在Java的子类与父类中有两个名称、参数列表都相同的方法的情况。由于他们具有相同的方法签名，所以子类中的新方法将覆盖父类中原有的方法。</span></p>
  <p data-lake-id="u2f023287" id="u2f023287"><span data-lake-id="u13908a45" id="u13908a45">​</span><br></p>
  <pre lang="java"><code>
class Parent {
    // 父类的方法
    public void display() {
        System.out.println("Parent display()");
    }
}

class Child extends Parent {
    // 子类重写了父类的方法
    @Override
    public void display() {
        System.out.println("Child display()");
    }
}

public class Main {
    public static void main(String[] args) {
        Parent obj1 = new Parent();
        obj1.display();  // 输出 "Parent display()"

        Parent obj2 = new Child();
        obj2.display();  // 输出 "Child display()"
    }
}

</code></pre>
  <p data-lake-id="u847afa4d" id="u847afa4d"><span data-lake-id="u8c454061" id="u8c454061">​</span><br></p>
  <h4 data-lake-id="X4Blp" id="X4Blp"><span data-lake-id="u0930c9e2" id="u0930c9e2">重载和重写的区别</span></h4>
  <p data-lake-id="u4a7fcba9" id="u4a7fcba9"><br></p>
  <p data-lake-id="u6d21433c" id="u6d21433c"><span data-lake-id="u00ca43ae" id="u00ca43ae">1、重载是一个编译期概念、重写是一个运行期间概念。</span></p>
  <p data-lake-id="u88ecd155" id="u88ecd155"><span data-lake-id="ufaa3e77e" id="ufaa3e77e">2、重载遵循所谓“编译期绑定”，即在编译时根据参数变量的类型判断应该调用哪个方法。</span></p>
  <p data-lake-id="u8c592440" id="u8c592440"><span data-lake-id="ud7564d47" id="ud7564d47">3、重写遵循所谓“运行期绑定”，即在运行的时候，根据引用变量所指向的实际对象的类型来调用方法</span></p>
  <p data-lake-id="u361d0db2" id="u361d0db2"><span data-lake-id="uc4c5e0d5" id="uc4c5e0d5">​</span><br></p>
 </body>
</html>